package com.jack.vipmis.vip.api.web.controller;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadBase;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

import com.jack.vipmis.common.Constants;
import com.jack.vipmis.common.utils.ImagesUtils;
import com.jack.vipmis.common.utils.LogUtils;
import com.jack.vipmis.common.utils.MessageUtils;
import com.jack.vipmis.common.utils.security.Coder;
import com.jack.vipmis.common.web.entity.AjaxUploadResponse;
import com.jack.vipmis.common.web.upload.FileUploadUtils;
import com.jack.vipmis.common.web.upload.exception.FileNameLengthLimitExceededException;
import com.jack.vipmis.common.web.upload.exception.InvalidExtensionException;
import com.jack.vipmis.vip.api.util.MsgUtil;

/**
 * 
 * @author JackLiang
 * @date 2014-7-16
 * @version 1.0
 */
@Controller
@RequestMapping(value = "api")
public class AjaxUploadApiController {
	// 最大上传大小 字节为单位
	private long		maxSize				= FileUploadUtils.DEFAULT_MAX_SIZE;
	// 允许的文件内容类型
	private String[]	allowedExtension	= FileUploadUtils.IMAGE_EXTENSION;
	// 文件上传下载的父目录
	private String		baseDir				= FileUploadUtils.getDefaultBaseDir();
	
	private static int	counter				= 0;

	/**
	 * 
	 * @param request
	 * @param response
	 * @return
	 */
	@RequestMapping(value = "uploadTest", method = RequestMethod.POST)
	@ResponseBody
	public Map<String, Object> upload(HttpServletRequest request, HttpServletResponse response) {
		try {
			// 1、创建工厂类：DiskFileItemFactory
			DiskFileItemFactory facotry = new DiskFileItemFactory();
			String tempDir = request.getServletContext().getRealPath("/WEB-INF/temp");
			facotry.setRepository(new File(tempDir));// 设置临时文件存放目录
			// 2、创建核心解析类：ServletFileUpload
			ServletFileUpload upload = new ServletFileUpload(facotry);
			upload.setHeaderEncoding("UTF-8");// 解决上传的文件名乱码
			upload.setFileSizeMax(1024 * 1024 * 1024);// 单个文件上传最大值是1M
			upload.setSizeMax(2048 * 1024 * 1024);// 文件上传的总大小限制

			// 3、判断用户的表单提交方式是不是multipart/form-data
			boolean bb = upload.isMultipartContent(request);
			if (!bb) {
				return null;
			}
			// 4、是：解析request对象的正文内容List<FileItem>
			List<FileItem> items = upload.parseRequest(request);
			String storePath = request.getServletContext().getRealPath("/WEB-INF/upload");// 上传的文件的存放目录
			for (FileItem item : items) {
				if (item.isFormField()) {
					// 5、判断是否是普通表单：打印看看
					String fieldName = item.getFieldName();// 请求参数名
					String fieldValue = item.getString("UTF-8");// 请求参数值
					System.out.println(fieldName + "=" + fieldValue);
				} else {
					// 6、上传表单：得到输入流，处理上传：保存到服务器的某个目录中
					String fileName = item.getName();
					// 解决用户没有选择文件上传的情况
					if (fileName == null || fileName.trim().equals("")) {
						continue;
					}
					fileName = fileName.substring(fileName.lastIndexOf("\\") + 1);
					System.out.println("上传的文件名是：" + fileName);
					InputStream in = item.getInputStream();
					String savePath = makeDir(storePath, fileName) + "\\" + fileName;
					OutputStream out = new FileOutputStream(savePath);
					byte b[] = new byte[1024];
					int len = -1;
					while ((len = in.read(b)) != -1) {
						out.write(b, 0, len);
					}
					in.close();
					out.close();
					item.delete();// 删除临时文件
				}
			}
		} catch (FileUploadBase.FileSizeLimitExceededException e) {
			e.printStackTrace();
		} catch (FileUploadBase.SizeLimitExceededException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 上传图片到服务器
	 * 
	 * @param request
	 * @param response
	 * @return
	 */
	@RequestMapping(value = "uploadImage")
	@ResponseBody
	public Map<String, Object> uploadImage(HttpServletRequest request, HttpServletResponse response) {
		InputStream in = null;
		FileOutputStream out = null;
		try {
			// 设置编码
			response.setCharacterEncoding("utf-8");
			// 获取流
			in = request.getInputStream();
			System.out.println(in.available());
			// 保存的路径
			String savePath = request.getServletContext().getRealPath("/upload");
			File saveFile = new File(savePath);
			if (!saveFile.exists()) {
				saveFile.mkdir();
			}
			String fileName = Coder.encryptMD5(System.nanoTime() + counter + "") + ".jpg";
			String filePath = savePath + "/" + FileUploadUtils.datePath() + "/" + fileName;
			out = new FileOutputStream(new File(filePath));
			BufferedReader bf = new BufferedReader(new InputStreamReader(in));
			byte b[] = new byte[1024];
			int len = 0;
			if ((len = bf.read()) != -1) {
				out.write(b, 0, len);
			}
			in.close();
			out.flush();
			return MsgUtil.doneOk(filePath);

		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				if (in != null) {
					in.close();
				}
				if (out != null) {
					out.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return MsgUtil.doneFail();
	}

	/**
	 * @param request
	 * @param files
	 * @return
	 */
	@RequestMapping(value = "ajaxUpload", method = RequestMethod.POST)
	@ResponseBody
	public AjaxUploadResponse ajaxUpload(HttpServletRequest request, HttpServletResponse response,
			@RequestParam(value = "files[]", required = false) MultipartFile[] files) {

		// The file upload plugin makes use of an Iframe Transport module for
		// browsers like Microsoft Internet Explorer and Opera, which do not yet
		// support XMLHTTPRequest file uploads.
		response.setContentType("text/plain");

		AjaxUploadResponse ajaxUploadResponse = new AjaxUploadResponse();

		if (ArrayUtils.isEmpty(files)) {
			return ajaxUploadResponse;
		}

		for (MultipartFile file : files) {
			String filename = file.getOriginalFilename();
			long size = file.getSize();

			try {
				String url = FileUploadUtils.upload(request, baseDir, file, allowedExtension, maxSize, true);

				String deleteURL = "/ajaxUpload/delete?filename=" + URLEncoder.encode(url, Constants.ENCODING);
				if (ImagesUtils.isImage(filename)) {
					ajaxUploadResponse.add(filename, size, url, url, deleteURL);
				} else {
					ajaxUploadResponse.add(filename, size, url, deleteURL);
				}
				continue;
			} catch (IOException e) {
				LogUtils.logError("file upload error", e);
				ajaxUploadResponse.add(filename, size, MessageUtils.message("upload.server.error"));
				continue;
			} catch (InvalidExtensionException e) {
				ajaxUploadResponse.add(filename, size, MessageUtils.message("upload.not.allow.extension"));
				continue;
			} catch (FileUploadBase.FileSizeLimitExceededException e) {
				ajaxUploadResponse.add(filename, size, MessageUtils.message("upload.exceed.maxSize"));
				continue;
			} catch (FileNameLengthLimitExceededException e) {
				ajaxUploadResponse.add(filename, size, MessageUtils.message("upload.filename.exceed.length"));
				continue;
			}
		}

		return ajaxUploadResponse;
	}

	/**
	 * 
	 * @param request
	 * @param filename
	 * @return
	 * @throws Exception
	 */
	@RequestMapping(value = "ajaxUpload/delete", method = RequestMethod.POST)
	@ResponseBody
	public String ajaxUploadDelete(HttpServletRequest request, @RequestParam(value = "filename") String filename)
			throws Exception {

		if (StringUtils.isEmpty(filename) || filename.contains("\\.\\.")) {
			return "";
		}
		filename = URLDecoder.decode(filename, Constants.ENCODING);

		String filePath = FileUploadUtils.extractUploadDir(request) + "/" + filename;

		File file = new File(filePath);
		file.deleteOnExit();

		return "";
	}

	/**
	 * 
	 * @param storePath
	 * @param fileName
	 * @return
	 */
	private String makeDir(String storePath, String fileName) {
		int hashCode = fileName.hashCode();// 得到文件名的hashcode码
		int dir1 = hashCode & 0xf;// 取hashCode的低4位 0~15
		int dir2 = (hashCode & 0xf0) >> 4;// 取hashCode的高4位 0~15
		String path = storePath + "\\" + dir1 + "\\" + dir2;
		File file = new File(path);
		if (!file.exists())
			file.mkdirs();
		return path;
	}
}
